import {
	App,
	defineComponent,
	PropType,
	VNode,
	Plugin,
	ref,
	toRaw,
	nextTick,
	renderSlot,
	computed,
	watchEffect,
} from 'vue'
import { useCustomTable } from './UseCustomTable'
import {
	FullscreenOutlined,
	SettingOutlined,
	FullscreenExitOutlined,
	ReloadOutlined,
	CaretUpOutlined,
	CaretDownOutlined,
} from '@ant-design/icons-vue'
import { useFullscreen } from './UseFullscreen'
import { clone, isEmpty, isNil, forEachObjIndexed, has, equals, map, find, findIndex, mergeRight } from 'ramda'
import { round } from '@/utils/tools'
type Size = 'default' | 'middle' | 'small'
interface Sorters {
	asc: boolean
	column: string
}
const props = {
	columns: {
		type: Object as PropType<Array<F.TableColumns>>,
		default: true,
	},
	tableLayout: {
		type: String as PropType<string>,
		default: 'auto',
	},
	dataSource: {
		type: Object as PropType<Array<any>>,
		default: [],
	},
	showTool: {
		type: Boolean as PropType<boolean>,
		default: true,
	},
	size: String as PropType<Size>,
	loading: Boolean as PropType<boolean>,
	rowKey: String as PropType<string>,
	title: [Function, String] as PropType<() => any | string>,
	scroll: Object as PropType<{ x?: number | true; y?: number }>,
	bordered: Boolean as PropType<boolean>,
	customRow: Function as PropType<<T>(data: T, index: number) => any>,
	expandedRowRender: Function as PropType<<T>(data: T) => VNode>,
	rowSelection: Object,
	expandIconAsCell: Boolean as PropType<boolean>,
	refresh: Function as PropType<() => void>,
	pagination: {
		type: Boolean as PropType<boolean>,
		default: false,
	},
	uniqueKey: String as PropType<string>,
	tableKey: {
		type: String as PropType<string>,
		required: true,
	},
	expandIcon: Function as PropType<<T>(porps: T) => VNode>,
	expandRowByClick: Boolean as PropType<boolean>,
	expandIconColumnIndex: Number as PropType<number>,
	indentSize: Number as PropType<number>,
	rowClassName: Function as PropType<<T>(record: T, index: number) => string>,
	getPopupContainer: Function as PropType<<T>(triggerNode: T) => HTMLElement>,
	defaultExpandAllRows: Boolean as PropType<boolean>,
	defaultExpandedRowKeys: Array as PropType<Array<string>>,
	expandedRowKeys: Array as PropType<Array<string>>,
	//  使用默认的统计 传入需要统计的字段 ['字段'] 注意 如果传入 summary 那么  showSummary 将无效
	showSummary: Array as PropType<string[]>,
	// 使用自定义统计 函数 入参是  dataSource  需要还会一条 记录  这条记录会被追加到  统计里面 需要注意的是 记录里存在的字段要跟 columns 一致
	// 使用统计之后 额外的添加行 如：操作那一栏  需要添加  record.isSummary 判断   record.isSummary ？ null : <a>点我</a>
	summary: Function as PropType<<T>(dataSource: T) => any>,
}

const FTable = defineComponent({
	components: { FullscreenOutlined, SettingOutlined, FullscreenExitOutlined, ReloadOutlined },
	name: 'f-table',
	props: props,
	emits: {
		sortersChange: Function as unknown as (value?: Array<Sorters>) => void,
	},
	setup(props, ctx) {
		const { visible, toggle, initColumns, tableColumns, saveColumns, columns: httpColumns } = useCustomTable()
		const sorters = ref<Array<Sorters>>([]) // 排序
		const { isFullScreen, toggle: fullScreenToggle } = useFullscreen('.app-main')
		const dataSource = ref(props.dataSource)
		const tableWidth = ref(0)
		watchEffect(() => {
			initColumns(props.columns, props.uniqueKey ?? props.tableKey)
		})
		watchEffect(() => {
			tableWidth.value = tableColumns.value.reduce((a, b) => {
				return a + (b.width ?? 0)
			}, 0)
		})
		const scroll = computed(() => {
			if (tableY.value <= 0) {
				return { x: true } ?? {}
			}
			return mergeRight(
				{
					y: tableY.value,
				},
				{ x: tableWidth.value }
			)
		})
		const tableY = ref(props.tableKey ? Number(localStorage.getItem(props.tableKey + 'tableY') ?? '550') : 550)
		watchEffect(() => {
			const data = thisUmmary()
			if (!isNil(data) && !isEmpty(data)) {
				dataSource.value = [...props.dataSource, data]
			} else {
				dataSource.value = props.dataSource
			}
		})
		const columns = computed(() => {
			return map((item) => {
				if (isNil(item.label) || isEmpty(item.label)) {
					item.label = item.title
				}
				if (isNil(item.width)) {
					if (item.key === 'action') {
						item.width = 150
					} else {
						item.width = item.label.length * 14 + 32
					}
				}
				if (item.sorter) {
					item.title = titleRender(item.title, item.dataIndex || item.key || '') as any
				}
				delete item.sorter
				return item
			}, tableColumns.value)
		})

		function sortersColor(key: string, doType: 'up' | 'down'): string {
			if (key) {
				const data = find((item) => equals(item.column, key), sorters.value)
				if (isNil(data)) {
					return '#666'
				}
				if (data.asc) {
					return doType === 'up' ? '#1890ff' : '#666'
				} else {
					return doType === 'down' ? '#1890ff' : '#666'
				}
			}
			return '#666'
		}
		function sortersStatus(column: string, doType: 'up' | 'down') {
			let data: Sorters | undefined
			return () => {
				if (isNil(data)) {
					data = find((item) => equals(item.column, column), sorters.value)
				}
				const asc = equals(doType, 'up')
				if (isNil(data)) {
					sorters.value.push({
						column,
						asc,
					})
				} else {
					const index = findIndex((item) => equals(item.column, column), sorters.value)
					if (data.asc === asc) {
						sorters.value.splice(index, 1)
					} else {
						sorters.value.splice(index, 1, {
							column,
							asc,
						})
					}
				}
				ctx.emit('sortersChange', sorters.value)
			}
		}
		function titleRender(title: string, key: string) {
			return () => (
				<div class="app-flex">
					<span>{title}</span>
					<span style={{ marginLeft: '10px' }}>
						<CaretUpOutlined
							style={{ color: sortersColor(key, 'up') }}
							onClick={sortersStatus(key, 'up')}
							class="outlined"
						/>
						<CaretDownOutlined
							style={{ color: sortersColor(key, 'down') }}
							onClick={sortersStatus(key, 'down')}
							class="outlined"
						/>
					</span>
				</div>
			)
		}
		function submit(data: F.Column[], tableYInput: number) {
			nextTick(() => {
				if (isEmpty(data) && props.tableKey) {
					localStorage.removeItem(props.tableKey)
					initColumns(props.columns, props.tableKey)
				} else {
					saveColumns(data)
					localStorage.setItem(props.tableKey + 'tableY', tableYInput.toString())
					tableY.value = tableYInput
				}
			})
		}

		function thisUmmary() {
			if (!isNil(props.dataSource) && !isEmpty(props.dataSource)) {
				const { showSummary, summary } = props
				if (summary) {
					// 存在自定义函数
					const data = summary(clone(toRaw(props.dataSource)))
					if (data) {
						data.isSummary = true
					}
					return data
				} else if (!isNil(showSummary) && !isEmpty(showSummary)) {
					const data: any = {
						isSummary: true,
					}
					const column = columns.value[0]
					props.dataSource.forEach((item, index) => {
						forEachObjIndexed((value, key) => {
							const _key = key as string
							if (column && equals(column.dataIndex, _key)) {
								data[_key] = '合计'
							} else if (showSummary.includes(_key)) {
								if (has(_key as string, data)) {
									data[_key] = Number(value) + (data[_key] as number)
								} else {
									data[_key] = Number(value)
								}
								if (equals(index, props.dataSource.length - 1)) {
									if (isNaN(data[_key])) {
										data[_key] = 'N/A'
									} else {
										data[_key] = round(data[_key], 3)
									}
								}
							} else {
								data[_key] = undefined
							}
						}, item)
					})
					return data
				}
			}
			return undefined
		}
		return () => {
			// const { columns: propsColumns, refresh, showTool, dataSource: PropsDataSource, ...tableProps } = props
			const { refresh, showTool, ...tableProps } = props
			const { header, ...slots } = ctx.slots
			return (
				<div>
					<div class="table-top" style="display: flex;align-items: center;">
						{header && renderSlot(ctx.slots, 'header')}
						{showTool && (
							<div class="ant-space-item" style="text-align: right;flex: 1;">
								{refresh ? (
									<a-tooltip placement="topLeft" onClick={refresh} title="刷新">
										<ReloadOutlined style="margin-left: 16px;" />
									</a-tooltip>
								) : null}
								<a-tooltip placement="topLeft" onClick={toggle} title="自定义显示">
									<SettingOutlined style="margin-left: 16px;" />
								</a-tooltip>
								<a-tooltip placement="topLeft" onClick={fullScreenToggle} title="全屏">
									{isFullScreen.value ? (
										<FullscreenExitOutlined style="margin-left: 16px;" />
									) : (
										<FullscreenOutlined style="margin-left: 16px;" />
									)}
								</a-tooltip>
							</div>
						)}
					</div>
					<a-table
						{...tableProps}
						v-slots={{ ...slots }}
						scroll={scroll.value}
						pagination={false}
						class="r-table"
						dataSource={dataSource.value}
						onChange={ctx.attrs.onChange}
						columns={columns.value}
					/>
					<f-configure
						v-model={visible.value}
						onSubmit={submit}
						title="表单自定义"
						tableY={tableY.value}
						columns={clone(toRaw(httpColumns.value))}
					/>
				</div>
			)
		}
	},
})

FTable.install = function (app: App) {
	app.component(FTable.name as string , FTable)
	return app
}

export default FTable as typeof FTable & Plugin
